/**
 * Copyright 2002 Cordys R&D B.V. 
 * 
 * This file is part of the Cordys .NET Connector. 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 /**
 * @author  owarnier
 * changed by pkavuri
 */


package com.eibus.applicationconnector.ejb;

import com.eibus.util.logger.CordysLogger;

import static com.eibus.util.logger.Severity.WARN;
import com.eibus.xml.nom.Node;
import com.eibus.xml.xpath.XPath;

class EJBObjectMetaData {
    /** MetaData EJB type */
    static final int EJB_TYPE_UNDEFINED = 0;
    /** MetaData EJB type */
    static final int EJB_TYPE_ENTITY = 1;
    /** MetaData EJB type */
     static final int EJB_TYPE_SESSION = 2;
    private int type = EJB_TYPE_UNDEFINED;
    /** Name of the EJB as in tje ejb-jar.xml file */
    private String ejbName;
    /** Name of the Home interface that is remotely available */
    private String remoteHomeName;
    /** Name of the Remote (actual implementing the methods to be called) interface of the EJB */
    private String remoteName;
    /** Name of the class implementing the methods */
    private String ejbClass;
    /** Type of session (when it is a session bean */
    private int sessionType = -1;
    /** Type of transaction (specified in the ejb-jar file) */
    private int transactionType = -1;
    /** @todo a way to store the different methods available on the home and remote interface of the EJB */
    
    private String ejbJndiName ="";
    
    /*Static xpath Objects*/
    public static String ejbnameXpath = ".//ejb-name";
    private static String homeXpath = ".//home";
    private static String remoteXpath = ".//remote";
    private static String ejbclassXpath =".//ejb-class";
    private static String sessionXpath = ".//session-type";
    private static String transactionXpath = ".//transaction-type";
    private static String persistenceXpath = ".//persistence-type";
    
    static CordysLogger ejbLogger = CordysLogger.getCordysLogger(EJBObjectMetaData.class);
    //private List methods;
    /** Creates a new instance of EJBObjectMetaData */
     EJBObjectMetaData() {
    }
    
    /** Creates a new instance of EJBObjectMetaData
     * pass the Element "session" or "entity" of the ejb-jar standards file within the deployment jar
     * <b>Do not pass the complete ejb-jar file !</b> Just one part containing a session or entity bean
     *  @param the element that contains the <session> or <entity> tag out of the ejb-jar.xml file
     */
     EJBObjectMetaData(int partOfEJBJarXML) throws EJBCallException {
        
         /*@todo for Message driven beans */
        String ejbType = Node.getName(partOfEJBJarXML);
        if (ejbType !=null)
            ejbType=ejbType.trim();
        else
            throw new EJBCallException("Improper Bean. Bean is Corrupted!!!!");
            
		// Finding the name of deployed bean,
		//int[] selection = Find.match(partOfEJBJarXML, "?<ejb-name>"); // .//ejb-name
		//int[] selection = ejbnameXpath.selectElementNodes(partOfEJBJarXML);
		int[] selection = XPath.getMatchingNodes(ejbnameXpath, null, partOfEJBJarXML);
		if (selection.length != 1) {
			if (ejbLogger.isWarningEnabled())
				ejbLogger.log(WARN,"too less or too many tags of ejb-name found:" + selection.length);
			
			throw new EJBCallException("too less or too many tags of ejb-name found");
		}
		else {
			ejbName = Node.getData(selection[0]);
			
		}
		// Finding the Home interface details.
		//selection = Find.match(partOfEJBJarXML,"?<home>");       // .//home
		//selection = homeXpath.selectElementNodes(partOfEJBJarXML);
		selection = XPath.getMatchingNodes(homeXpath, null, partOfEJBJarXML);
		if (selection.length != 1) {
			if (ejbLogger.isWarningEnabled())
				ejbLogger.log(WARN,"too less or too many tags of home found:" + selection.length);
			
			throw new EJBCallException("too less or too many tags of  of home found");
		}
		else {
			remoteHomeName = Node.getData(selection[0]);;

		}
		// Find remote interface details.
		//selection = Find.match(partOfEJBJarXML,"?<remote>");  // .//remote
		//selection = remoteXpath.selectElementNodes(partOfEJBJarXML);
		selection = XPath.getMatchingNodes(remoteXpath, null, partOfEJBJarXML);
		if (selection.length != 1) {
			if (ejbLogger.isWarningEnabled())
				ejbLogger.log(WARN,"too less or too many tags of remote found " + selection.length);
			throw new EJBCallException("too less or too many tags of  of remote found");
		}
		else {
			remoteName = Node.getData(selection[0]);
		}
		// Finding the implementation class.
		//selection = Find.match(partOfEJBJarXML,"?<ejb-class>"); // .//ejb-calss
		//selection = ejbclassXpath.selectElementNodes(partOfEJBJarXML);
		selection = XPath.getMatchingNodes(ejbclassXpath, null, partOfEJBJarXML);
		if (selection.length != 1) {
			if (ejbLogger.isWarningEnabled())
				ejbLogger.log(WARN,"too less or too many tags of ejb-class found " + selection.length);
	
			throw new EJBCallException("too less or too many tags of ejb-class found:");
		}
		else {
			ejbClass = Node.getData(selection[0]);
		}
            
        if ("session".equalsIgnoreCase(ejbType)) {
            type = EJB_TYPE_SESSION;
            handleSessionBeans(partOfEJBJarXML);
        }
        else if ("entity".equalsIgnoreCase(ejbType)) {
            type = EJB_TYPE_ENTITY;
			handleEntityBeans(partOfEJBJarXML);
        }
        if(partOfEJBJarXML > 0)
        {
        	Node.delete(partOfEJBJarXML);
        	partOfEJBJarXML = 0;
        }
    }
    
    private void handleSessionBeans(int partOfEJBJarXML ) throws EJBCallException {
		// for session-types
		int[] selection = null;
		//selection = Find.match(partOfEJBJarXML,"?<session-type>");   // .//session-type
		//selection = sessionXpath.selectElementNodes(partOfEJBJarXML);
		selection = XPath.getMatchingNodes(sessionXpath, null, partOfEJBJarXML);
		if (selection.length != 1) {
			if (ejbLogger.isWarningEnabled())
				ejbLogger.log(WARN,"too less or too many tags of session-type found " + selection.length);
				throw new EJBCallException("too less or too many tags of session-type found:");
		}
		else {
			if ("Stateful".equalsIgnoreCase(Node.getData(selection[0]).trim()))
				sessionType = 1;
			else
				sessionType = 0;
		}
	
		//	For transaction-type
		//selection = Find.match(partOfEJBJarXML,"?<transaction-type>");  // .//transaction-type
		//selection = transactionXpath.selectElementNodes(partOfEJBJarXML);
		selection = XPath.getMatchingNodes(transactionXpath, null, partOfEJBJarXML);
		if (selection.length != 1) {
		if (ejbLogger.isWarningEnabled())
				ejbLogger.log(WARN,"too less or too many tags of transaction-type found " + selection.length);
			 throw new EJBCallException("too less or too many tags of transaction-type found:");
		 }
		 else {
			 if ("Container".equals(Node.getData(selection[0]).trim()))
				 transactionType = 1;
			 else
				 transactionType = 0;
				 }
    }
    
	private void handleEntityBeans(int partOfEJBJarXML ) throws EJBCallException {
		int[] selection = null;
		//selection = Find.match(partOfEJBJarXML,"?<persistence-type>"); // .//persistence-type
		//selection = persistenceXpath.selectElementNodes(partOfEJBJarXML);
		selection = XPath.getMatchingNodes(persistenceXpath, null, partOfEJBJarXML);
		if (selection.length != 1) {
			if (ejbLogger.isWarningEnabled())
				ejbLogger.log(WARN,"too less or too many tags of persistence-type found " + selection.length);
				throw new EJBCallException("too less or too many tags of persistence-type found:");
		}
		else {
			if ("Container".equalsIgnoreCase(Node.getData(selection[0]).trim()))
				sessionType = 1;
			else
				sessionType = 0;
		}
		transactionType = sessionType;
	} 
    
     String getName() {
        return ejbName;
    }
    
     String getRemoteHomeName() {
        return remoteHomeName;
    }
    
     String getRemoteName() {
        return remoteName;
    }
     String getEjbClass() {
        return ejbClass;
    }
    
     String getEJBType(){
        if (type == 0) return "Undefined";
        if (type == 1) return "Entity";
        return "Session";
    }
    
     String getSessionType() {
     	if (type == 1) {
			if (sessionType == -1) return "Undefined";
			if (sessionType == 1) return "CMP";
			return "BMP";
     	}
        if (sessionType == -1) return "Undefined";
        if (sessionType == 1) return "Stateful";
        return "Stateless";
    }
    
     String getTransactionType() {
        if (transactionType == -1) return "Undefined";
        if (transactionType == 1) return "Container";
        return "Application";
    }

	public String getEjbJndiName() {
		return ejbJndiName;
	}

	public void setEjbJndiName(String ejb_jndi_name) {
		this.ejbJndiName = ejb_jndi_name;
	}
}
